package gr.handson.test;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.Closeable;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class Process {

	private static final String EXC = "Passing arguments should have a length of 3 \n";
	protected static final int numParams = 3;
	
	private List<String> sortedStringsIn = new ArrayList<String>();
	private List<String> sortedStringsOut = new ArrayList<String>();
	
	private String inputFileName1;
	private String inputFileName2;
	private String outputFileName;


	public Process(String[] args) {
		if (args == null || args.length != numParams) {
			throw new IllegalArgumentException(EXC);
		}
		inputFileName1 = args[0];
		inputFileName2 = args[1];
		outputFileName = args[2];
	}

	/**
	 * The applied algorithm is as follows:
	 * - store the contents of the first input file in a list, 
	 * - convert the contents to a Set and then back again in order to remove duplicates,
	 * - sort the elements,
	 * - iterate through the elements of the second input file and search each line against the sorted list
	 * - if the String is found, then store it in a second list and remove the element from the first list preventing finding a duplicate,
	 * - sort the second list and print the contents in the output file
	 * 
	 */
	public void startProcessing() {

		BufferedReader brInput1 = null;
		BufferedReader brInput2 = null;
		PrintWriter printWriter = null;
		
		try {
			// store contents of first file
			brInput1 = new BufferedReader(new FileReader(inputFileName1));
			String line;
			// add every line of the file in the list of sorted strings
			while ((line = brInput1.readLine()) != null) {
				sortedStringsIn.add(line);
			}
			
			// remove duplicates (if any) by adding all to a set and then back to the list again
			Set<String> hs = new HashSet<String>();
			hs.addAll(sortedStringsIn);
			sortedStringsIn.clear();
			sortedStringsIn.addAll(hs);
			
			// sort the list of strings from the first input file
			Collections.sort(sortedStringsIn);
			
			brInput2 = new BufferedReader(new FileReader(inputFileName2));
			printWriter = new PrintWriter(new BufferedWriter(new FileWriter(outputFileName)));
			while ((line = brInput2.readLine()) != null) {
				int index = Collections.binarySearch(sortedStringsIn, line);
				// in case the string exists in the list
				if (index >= 0) {
					// add it to the output list
					sortedStringsOut.add(line);
					// and remove it from the list so that it cannot be matched again
					sortedStringsIn.remove(index);
				}
			}
			
			// sort the list of strings from the second input file
			Collections.sort(sortedStringsOut);
			for (String str : sortedStringsOut) {
				printWriter.println(str);
			}
			
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			// do not forget to close all readers and writers!
			close(brInput1);
			close(brInput2);
			close(printWriter);
		}

	}

	private static void close(Closeable c) {
		if (c == null)
			return;
		try {
			c.close();
		} catch (IOException e) {
			// log the exception
		}
	}

}
